import CustomRender from "./CustomRenderV3";

const gfx = cc['gfx'];

let vfmtPosUvColorFront = new gfx.VertexFormat([
    // 节点的世界坐标，占2个float32
    { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },

    // 节点的纹理uv坐标，占2个float32
    // 如果节点使用了独立的纹理（未合图），这里的uv值通常是0或1
    // 合图后的纹理，这里的uv对应其在图集里的相对位置，取值范围在[0,1)内
    { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },

    // 节点颜色值，占4个uint8 = 1个float32
    { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true },
]);

export default class CustomAssemblerV3 extends cc.Assembler {
    // 普通四边形的属性，根据实际的顶点格式、数量调整

    /** 四边形顶点数量 = 4 */
    protected verticesCount = 4;

    /** 一个四边形按照对角拆分成2个三角形，2*3 = 6个顶点索引 */
    protected indicesCount = 6;

    /** vfmtPosUvColor 结构占5个float32 */
    protected floatsPerVert = 5;

    /** vdata offset info (default = 2) */
    protected uvOffset = 2;

    /** 颜色取值偏移 (default = 4) */
    protected colorOffset = 4;

    protected _renderData: cc.RenderData = null;

    public updateRenderData(comp: cc.RenderComponent) {
        if (comp._vertsDirty) {
            // this.updateUVs(comp);
            // this.updateVerts(comp);
            this.updateUVVerts(comp);
            comp._vertsDirty = false;
        }
    }

    /**
     * @override
     * @dec 初始化 `_renderData` 数据
     */
    init(comp: any) {
        super.init(comp);

        let count = comp.getPointCount() - 1;

        let segmentCount = count * count;
        this.verticesCount = 4 * segmentCount;
        this.indicesCount = 6 * segmentCount;
        this.floatsPerVert = 5;

        this._renderData = new cc.RenderData();
        this._renderData.init(this);

        this.initData();
    }

    /** 当前节点的所有顶点数据总大小 */
    get verticesFloats() {
        return this.verticesCount * this.floatsPerVert;
    }

    initData() {
        let data = this._renderData;
        data.createQuadData(0, this.verticesFloats, this.indicesCount);
    }

    /** 更新颜色 */
    updateColor(comp: any, color: any) {
        let uintVerts = this._renderData.uintVDatas[0];
        if (!uintVerts) return;
        color = color != null ? color : comp.node.color._val;
        let floatsPerVert = this.floatsPerVert;
        let colorOffset = this.colorOffset;
        for (let i = colorOffset, l = uintVerts.length; i < l; i += floatsPerVert) {
            uintVerts[i] = color;
        }
    }

    /**
     * 重载getBuffer(), 默认fillBuffers()方法中会调用到
     * @returns 返回一个能容纳自定义顶点数据的buffer
     */
    getBuffer() {
        //@ts-ignore
        return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
    }

    getVfmt() {
        return vfmtPosUvColorFront;
    }

    updateUVVerts(comp: any) {
        let pointNum: number = comp.getPointCount();

        /** vdata offset info (default = 2) */
        let uvOffset = this.uvOffset;

        /** vfmtPosUvColor 结构占5个float32 */
        let floatsPerVert = this.floatsPerVert;

        /** 
         * @dec renderData.vDatas 用来存储 pos, uv, color 数据 
         * @dec pos.x, pos.y, uv.x, uv.y, color
        */
        let verts = this._renderData.vDatas[0];

        let node = comp.node;
        let cw = node.width;
        let ch = node.height;

        /** 左下角X坐标 */
        let posX = - cw * node.anchorX;

        /** 左下角Y坐标 */
        let posY = - ch * node.anchorY;

        /** 上一个点的纹理坐标 */
        let lastUV = 0;

        /** 下一个点的纹理坐标 */
        let nextUV = 0;

        /** x 坐标偏移 */
        let posXOffset = cw / (pointNum - 1);

        /** y 坐标偏移 */
        let posYOffset = ch / (pointNum - 1);

        /** uv x 轴偏移 */
        let uvvXOffset = 1 / (pointNum - 1);

        /** uv x 轴偏移 */
        let uvvYOffset = 1 / (pointNum - 1);

        
        let count = pointNum - 1;
        for (let i = 0; i < count * count; i++) {
            var row = Math.floor(i / count);
            var col = Math.floor(i % count);

            let dstOffset = floatsPerVert * i * 4;

            // left bottom
            verts[dstOffset] = posX + col * posXOffset;
            verts[dstOffset + 1] = posY + ch - (row + 1) * posYOffset;
            verts[dstOffset + 2] = col * uvvXOffset;
            verts[dstOffset + 3] = (row + 1) * uvvYOffset;
            dstOffset += floatsPerVert;

            // cc.log('左下', 'i', i, 'row', row, 'col', col, 'u', col * uvvXOffset, 'v', (row + 1) * uvvYOffset);

            // right bottom
            verts[dstOffset] = posX + (col + 1) * posXOffset;
            verts[dstOffset + 1] = posY + ch - (row + 1) * posYOffset;
            verts[dstOffset + 2] = (col + 1) * uvvXOffset;
            verts[dstOffset + 3] = (row + 1) * uvvYOffset;
            dstOffset += floatsPerVert;

            // cc.log('右下', 'i', i, 'row', row, 'col', col, 'u', (col + 1) * uvvXOffset, 'v', (row + 1) * uvvYOffset);

            // left top
            verts[dstOffset] = posX + col * posXOffset;
            verts[dstOffset + 1] = posY + ch - row * posYOffset;
            verts[dstOffset + 2] = col * uvvXOffset;
            verts[dstOffset + 3] = row * uvvYOffset;
            dstOffset += floatsPerVert;

            // cc.log('左上', 'i', i, 'row', row, 'col', col, 'u', col * uvvXOffset, 'v', row * uvvYOffset);

            // right top
            verts[dstOffset] = posX + (col + 1) * posXOffset;
            verts[dstOffset + 1] = posY + ch - row * posYOffset;
            verts[dstOffset + 2] = (col + 1) * uvvXOffset;
            verts[dstOffset + 3] = row * uvvYOffset;

            // cc.log('右上', 'i', i, 'row', row, 'col', col, 'u', (col + 1) * uvvXOffset, 'v', row * uvvYOffset);
        }
    }

    fillBuffers(comp, renderer) {
        let renderData = this._renderData;
        let vData = renderData.vDatas[0];
        let iData = renderData.iDatas[0];

        let buffer = this.getBuffer();
        let offsetInfo = buffer.request(this.verticesCount, this.indicesCount);

        let vertexOffset = offsetInfo.byteOffset >> 2,
            vbuf = buffer._vData;

        if (vData.length + vertexOffset > vbuf.length) {
            vbuf.set(vData.subarray(0, vbuf.length - vertexOffset), vertexOffset);
        } else {
            vbuf.set(vData, vertexOffset);
        }

        let ibuf = buffer._iData,
            indiceOffset = offsetInfo.indiceOffset,
            vertexId = offsetInfo.vertexOffset;
        for (let i = 0, l = iData.length; i < l; i++) {
            ibuf[indiceOffset++] = vertexId + iData[i];
        }
    }
}
